#pragma once
#include "Player.h"
#include "common.h"
#ifndef CONNECTIONPROCESSOR_H
#define CONNECTIONPROCESSOR_H
#include "PlayerContainer.h"
#endif

#define CONNECTION_LOGININIT 14
#define CONNECTION_UPDATE 15
#define CONNECTION_LOGIN 16
#define CONNECTION_JAGGRAB 17
#define CONNECTION_RECONNECT 18

#define RESPONSE_LOGIN 0
#define RESPONSE_TRYAGAIN2S 1
#define RESPONSE_SUCCESS 2
#define RESPONSE_MISMATCH 3
#define RESPONSE_DISABLED 4
#define RESPONSE_ALREADYLOGGEDIN 5

const static int* get_ukeys(unsigned short revision) {
	return 0;
}

static Player* get_new_player(Socket* sock, PlayerContainer* container, char* username, char* password);

static Player* process_connection(Socket* s, PlayerContainer* container) {
	unsigned char c;
	cout << "stage 1\n";
	if(s->receive(&c, 1) != 1)
		return 0;
	unsigned char connection_type = c;
	unsigned short detail;
	unsigned int uid;
	int64_t server_key = 0;
	int64_t client_key;
	char* username;
	char* password;
	cout << "stage 2 type " << (int)connection_type << "\n";
	Buffer buffer = Buffer(100);

	switch(connection_type) {
		case CONNECTION_LOGININIT:
			if(s->receive(&c, 1) < 1)
				return 0;
			cout << "stage 3\n";
			buffer.read_byte(); //name hash
			buffer.data = buffer.start;
			buffer.write_long(0); //server session key
			buffer.write_byte(0); //0 for init
			buffer.write_long(0); //client session key
			if(s->send(buffer.start, buffer.data - buffer.start) < 17)
				return 0;
			cout << "stage 4\n";
			return process_connection(s, container);
		break;

		case CONNECTION_LOGIN:
		case CONNECTION_RECONNECT:
			if(s->receive(&c, 1) <= 0)
				return 0;
			if(s->receive(buffer.data, c) != c)
				return 0;
			cout << "packet size: " << (int)c << "\n";
			if(buffer.read_byte() != 255)
			{
				buffer.data--;
				cout << "warning: magic byte = " << buffer.read_byte() << "\n";
			}
			cout << "client version: " << (int)buffer.read_short() << "\n";
			detail = buffer.read_le_short();
			cout << "detail: " << (int)detail << "\n";
			for(int i = 0; i < 9; i++)
				buffer.read_int(); //crc values
			if((c = buffer.read_byte()) != 10)
				cout << "warning: magic byte = " << (int)c << "\n";
			client_key = buffer.read_long();
			server_key = buffer.read_long();
			if(server_key != 0) //server session key - it was sent as 0
				cout << "server session key mismatch\n";
			uid = buffer.read_int();
			cout << "uid = " << uid << "\n";
			username = buffer.read_string();
			password = buffer.read_string();
			cout << "username: " << username << "\n";
			cout << "password: " << password << "\n";

			c = RESPONSE_SUCCESS;
			if(connection_type != CONNECTION_RECONNECT && container->get_ngi_index(username) != -1)
				c = RESPONSE_ALREADYLOGGEDIN;

			buffer.data = buffer.start;
			buffer.write_byte(c);
			if(c != 2) {
				s->send(&c, 1);
				return 0;
			}
			buffer.write_byte(0); //rights
			buffer.write_byte(0); //flagged
			s->send(buffer.start, 3);

			if(connection_type == CONNECTION_RECONNECT) {
				uid = container->get_ngi_index(username);
				container->remove(container->nodes.nodes[uid], ((Entity*)container->nodes.nodes[uid])->entity_index);
			}

			return get_new_player(s, container, username, password);
			break;
	}

	return 0;
}

static Player* get_new_player(Socket* sock, PlayerContainer* container, char* username, char* password) {
	Player* p = new Player(sock, container->available_node_index(), 3333, 3333);
	p->username = username;
	p->password = password;
	return p;
}